import ListenerContainer.PLCVarSection;
import ListenerContainer.PLCVar_declsInfo;
import PLCSymbolAndScope.PLCScope.PLCScope;
import PLCSymbolAndScope.PLCSymbolTableGenerator;
import PLCSymbolAndScope.PLCSymbolTableGeneratorNew;
import PLCSymbolAndScope.PLCSymbolTables.PLCSymbolTable;
import PLCSymbolAndScope.PLCSymbols.*;
import antlr4.PLCSTPARSERBaseListener;
import antlr4.PLCSTPARSERParser;

import java.util.Objects;
import java.util.Stack;

public class PLCListener extends PLCSTPARSERBaseListener {

    public PLCSymbolTableGeneratorNew plcSymbolTableGeneratorNew = new PLCSymbolTableGeneratorNew();

    //生成器成员
    public PLCSymbolTableGenerator plcSymbolTableGenerator = new PLCSymbolTableGenerator();

    //变量段信息栈
    public Stack<PLCVarSection> varInfoStack = new Stack<>();

    //变量段内声明符号信息
    public Stack<PLCSymbol> varDeclSymbolStack = new Stack<>();

    //变量段内声明符号所用类型信息
    public Stack<PLCTypeDeclSymbol> varDeclTypeStack = new Stack<>();

    //变量段内

    //进入变量段声明
    @Override
    public void enterVar_decls(PLCSTPARSERParser.Var_declsContext ctx) {

        //创建变量段信息对象
        PLCVar_declsInfo plcVar_declsInfo = new PLCVar_declsInfo();

        //判断是否存在
        if(ctx.var_decl_init(0) != null){
            System.out.println("写不肉");
            System.out.println(ctx.var_decl_init(0).getText());

        }else {
            System.out.println("写不肉");
        }

        //检查是否是constant
        if (Objects.equals(ctx.getChild(1).getText(), "CONSTANT")){

            plcVar_declsInfo.ifConst = true;

        }

        //检查变量段访问修饰符
        if(ctx.Access_Spec()!=null){

            plcVar_declsInfo.accessModifier = 1;

        }

        //将变量段信息压入变量段信息栈中
        this.varInfoStack.push(plcVar_declsInfo);

    }

    @Override
    public void enterSimple_spec_init(PLCSTPARSERParser.Simple_spec_initContext ctx) {

    }

    @Override public void enterVardeclinit(PLCSTPARSERParser.VardeclinitContext ctx) {


    }

    //进入variable_list，获取声明的符号名称
    @Override
    public void enterVariable_list(PLCSTPARSERParser.Variable_listContext ctx) {
        //PLCVariable plcVariable = new PLCVariable(ctx.variable_name());
        //ctx.getChild(0).getText();

        //类型名
        System.out.println(ctx.getParent().getText());

        //创建symbol
        PLCVariable plcVariable = new PLCVariable(ctx.getChild(0).getText());

        //
        plcVariable.symbolId = this.plcSymbolTableGenerator.idGenerator.outPutIDNum();

        //
        this.varDeclSymbolStack.push(plcVariable);

        //
        int size = ctx.getChildCount();

        //继续获取子结点符号名称
        for (int j =0; j < size; j=j+2){

            //创建符号对象
            PLCVariable plcVariableOther = new PLCVariable(ctx.getChild(j).getText());

            //设置符号id
            plcVariableOther.symbolId = this.plcSymbolTableGenerator.idGenerator.outPutIDNum();

            //将符号声明加入符号栈
            this.varDeclSymbolStack.push(plcVariableOther);

            //
            System.out.println("当前符号id");
            System.out.println(plcVariableOther.symbolId);

        }

    }

    //离开variable_list，将符号全部加入符号表中
    @Override
    public void exitVariable_list(PLCSTPARSERParser.Variable_listContext ctx){
        while(!this.varDeclSymbolStack.empty()){

            //将符号全部弹出加入到ID符号表中
            this.plcSymbolTableGenerator.addSymbolToTotalSymbolTable(this.varDeclSymbolStack.peek());

            //将符号加入到当前作用域栈顶作用域的符号表
            this.plcSymbolTableGenerator.addSymbolToStackPeekTable(this.varDeclSymbolStack.peek());

            //将添加到符号表的符号出栈
            this.varDeclSymbolStack.pop();

        }

        //
        System.out.println(this.plcSymbolTableGenerator.totalSymbolTable.totalSymbolTable);
    }

    //进入class声明，生成class符号表以及相应的符号、作用域
    @Override
    public void enterClass_decl(PLCSTPARSERParser.Class_declContext ctx) {

        //创建classSymbol
        //PLCClassDeclSymbol plcClassDeclSymbol = this.plcSymbolTableGenerator.createPLCClassDeclSymbol(ctx.class_type_name().getText());

        //创建class对应的作用域以及符号表
        //PLCSymbolTable classSymbolTable = this.plcSymbolTableGenerator.createTableAndScope(plcClassDeclSymbol);

        //将class符号表加入总表
        //this.plcSymbolTableGenerator.addTableToTotalTable(classSymbolTable);

        //将class作用域加入总表
        //this.plcSymbolTableGenerator.addScopeToTotalSymbolTable(classSymbolTable.tableScope);

        //将class加入到声明所在作用域map和总表map中
        //this.plcSymbolTableGenerator.addPLCISSymbolToTable(plcClassDeclSymbol);


        //检查class是否是FINAL、ABSTRACT
        //if(Objects.equals(ctx.getChild(1).getText(), "FINAL") ){

            //
        //    plcClassDeclSymbol.classModifier = PLCModifierEnum.ClassModifier.FINAL;

        //}else if (Objects.equals(ctx.getChild(1).getText(), "ABSTRACT")){

            //
        //    plcClassDeclSymbol.classModifier = PLCModifierEnum.ClassModifier.ABSTRACT;

        //}

        //记录类的引入的命名空间


        //记录类继承的类


        //记录类实现的接口


        //将类作用域压栈
        //this.plcSymbolTableGenerator.pushScope(plcClassDeclSymbol.importScope);

        //创建class
        PLCClassDeclSymbol classSymbol = this.plcSymbolTableGeneratorNew.createClassSymbol(ctx.class_type_name().getText());

        //将class符号加入到所属符号表中
        this.plcSymbolTableGeneratorNew.addSymbolToSymbolTable(classSymbol);

        //创建class的符号表和作用域
        PLCSymbolTable classTable = this.plcSymbolTableGeneratorNew.createTableAndScope(classSymbol);

        //设置class符号到声明所属的符号表和作用域引用
        this.plcSymbolTableGeneratorNew.setSymbolToDeclTableRef(classSymbol, classTable);

        this.plcSymbolTableGeneratorNew.setSymbolToLocalScopeRef(classSymbol, classTable.tableScope);

        //检查class是否是abstract或者final
        if(Objects.equals(ctx.getChild(1).getText(), "FINAL") ){

            classSymbol.classModifier = PLCModifierEnum.ClassModifier.FINAL;

        }else if (Objects.equals(ctx.getChild(1).getText(), "ABSTRACT")){

            classSymbol.classModifier = PLCModifierEnum.ClassModifier.ABSTRACT;

        }

        //记录类的引入的命名空间
        if(ctx.using_directive() != null){
            System.out.println("UsingNamespace");
            int j = ctx.using_directive().namespace_h_name().size();
            int i ;
            for(i = 0; i < j; i++){

                //获取使用命名空间嵌套长度
                int n = ctx.using_directive().namespace_h_name(i).getChildCount()-1;

                //记录最后一个命名空间名字例如A.B.C,获取C
                String usNS = ctx.using_directive().namespace_h_name(i).getChild(n).getText();

                //从当前作用域开始静态检查找到该命名空间引用
                //搜索符号表找到该命名空间然后返回该对象加入到class符号对应的scope中


            }
        }
        //记录类继承的类
        if(ctx.class_type_access() !=null){

            System.out.println("Extends");

            int j = ctx.class_type_access().namespace_name().size();

            if(j != 0){
                //获取命名空间名称
                String extendsNS = ctx.class_type_access().namespace_name(j-1).getText();

            }

            //获取继承类名称
            String extendsClassName = ctx.class_type_access().class_type_name().getText();

            //该类进行静态检查，如果没有错误加入classScope的map下


        }

        //记录类实现的接口
        if(ctx.interface_name_list() !=null){

            System.out.println("Implements");

            //获取实现接口长度
            int j = ctx.interface_name_list().interface_type_access().size() - 1;

            for(int i =0; i < j; j++){

                //静态检查后将所有interface对象添加到classscope中
                int n = ctx.interface_name_list().interface_type_access(i).namespace_name().size();
                if(n != 0){
                    //
                    String impleNS = ctx.interface_name_list().interface_type_access(i).namespace_name(n-1).getText();

                    //获取该部分接口名称
                    String impleInterface = ctx.interface_name_list().interface_type_access(i).interface_type_name().getText();

                    //静态检查返回接口对象加入classScope对应的容器
                    //
                    //
                }

            }
        }

    }

    @Override
    public void exitClass_decl(PLCSTPARSERParser.Class_declContext ctx){

        //将class作用域弹出
        this.plcSymbolTableGenerator.popScope();

    }

    @Override
    public void enterFunc_decl(PLCSTPARSERParser.Func_declContext ctx) {

    }

    @Override
    public void exitFunc_decl(PLCSTPARSERParser.Func_declContext ctx) {

    }

    @Override
    public void enterData_type_access(PLCSTPARSERParser.Data_type_accessContext ctx) {

    }

    @Override public void enterUsing_directive(PLCSTPARSERParser.Using_directiveContext ctx) {

    }

    @Override public void exitVar_decls(PLCSTPARSERParser.Var_declsContext ctx) {

    }

}
